#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <jsoncpp/json/json.h>

const std::string blank_sep = " ";
const std::string protocol_sep = "\n";

std::string Encode(const std::string &content)
{
    std::string out = std::to_string(content.size());
    out += protocol_sep;
    out += content;
    out += protocol_sep;
    return out;
}

// "len\nx op y\n...."
bool Decode(std::string &package, std::string& content)
{
    size_t pos = package.find(protocol_sep);
    if(pos == std::string::npos) return false;

    std::string len_str = package.substr(0, pos);
    size_t len = std::stoi(len_str);
    size_t total_len = len + len_str.size() + 2;
    if(package.size() < total_len) return false;

    content = package.substr(pos+1, len);
    package.erase(0, total_len);
    return true;
}

// "len\nx op y\n"
class Request
{
public:
    Request(){}

    Request(int x, int y, char op)
        : _x(x), _y(y), _op(op)
    {
    }
    ~Request()
    {
    }

public:
    bool Serialize(std::string *out)
    {
#ifdef MySelf
        std::string s = std::to_string(_x);
        s += blank_sep;
        s += _op;
        s += blank_sep;
        s += std::to_string(_y);

        *out = s;
        return true;
#else
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["op"] = _op;

        Json::FastWriter w;
        *out = w.write(root);
        return true;
#endif
        
    }
    // "x + y"
    bool Deserialize(std::string s)
    {
#ifdef MySelf
        size_t pos1 = s.find(blank_sep);
        if (pos1 == std::string::npos)
            return false;
        size_t pos2 = s.find(blank_sep, pos1 + 1);
        if (pos2 == std::string::npos)
            return false;

        _x = std::stoi(s.substr(0, pos1));
        _y = std::stoi(s.substr(pos2 + 1));
        _op = s[pos1 + 1];
        return true;
#else
        Json::Value v;
        Json::Reader r;
        r.parse(s, v);
        _x = v["x"].asInt();
        _y = v["y"].asInt();
        _op= v["op"].asInt();
        return true;
#endif
    }

public:
    int _x;
    int _y;
    char _op;
};

// "len\nres code\n"
class Response
{
public:
    Response(){}

    Response(int res, int code)
        : _res(res), _code(code)
    {
    }
    ~Response()
    {
    }

public:
    bool Serialize(std::string *out)
    {
#ifdef MySelf
        std::string s = std::to_string(_res);
        s += blank_sep;
        s += std::to_string(_code);
        *out = s;

        return true;

#else 
        Json::Value root;
        root["res"] = _res;
        root["code"] = _code;

        Json::FastWriter w;
        *out = w.write(root);

        return true;
#endif
        
    }

    // "res code"
    bool Deserialize(std::string s)
    {
#ifdef MySelf
        size_t pos = s.find(blank_sep);
        if (pos == std::string::npos)
            return false;
        
        _res = std::stoi(s.substr(0, pos));
        _code = std::stoi(s.substr(pos+1));

        return true;
#else
        Json::Value v;
        Json::Reader r;

        r.parse(s, v);
        _res = v["res"].asInt();
        _code = v["code"].asInt();
        return true;
#endif
    }

    void DebugPrint()
    {
        std::cout << "成功拿到结果: result = " << _res << ", code= " << _code << std::endl;
    }
public:
    int _res;
    int _code;
};